package com.bestcem.xm.user.service.impl;

import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.bp.grpc.v1.base.Page;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.AuthErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.component.security.dto.TokenDTO;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.user.config.properties.MailSubjectNotifyTitleEnumProperties;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.config.properties.XunFeiYunProperties;
import com.bestcem.xm.user.constant.CommonConstant;
import com.bestcem.xm.user.constant.SmsConstant;
import com.bestcem.xm.user.dao.OrganizationDao;
import com.bestcem.xm.user.entity.pojo.ListOrgByPageDO;
import com.bestcem.xm.user.entity.pojo.ListOrgsByFilterDO;
import com.bestcem.xm.user.entity.pojo.OrganizationDO;
import com.bestcem.xm.user.enums.*;
import com.bestcem.xm.user.grpc.client.*;
import com.bestcem.xm.user.grpc.client.dto.*;
import com.bestcem.xm.user.grpc.service.converter.OrgConditionConvert;
import com.bestcem.xm.user.grpc.service.param.ListOrgByPageParam;
import com.bestcem.xm.user.grpc.service.param.ListOrgsByFilterParam;
import com.bestcem.xm.user.grpc.service.param.ListOrgsByPagingParam;
import com.bestcem.xm.user.service.*;
import com.bestcem.xm.user.service.dto.PageResponseDTO;
import com.bestcem.xm.user.service.dto.order.RecordToOmDTO;
import com.bestcem.xm.user.service.dto.user.*;
import com.bestcem.xm.user.util.business.CustomSettingThreadLocalUtil;
import com.bestcem.xm.user.util.business.StringFormatUtil;
import com.bestcem.xm.user.util.business.UserUtil;
import com.bestcem.xm.user.util.convert.OrganizationConvert;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.bestcem.xm.user.constant.SmsConstant.SMS_PRICE_MAX;
import static com.bestcem.xm.user.constant.SmsConstant.SMS_PRICE_MIN;

/**
 * 公司管理相关服务
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/1 14:43
 */
@Slf4j
@Service
public class OrganizationServiceImpl implements OrganizationService {

    @Resource
    private OrganizationDao organizationDao;

    @Resource
    private OrganizationConvert organizationConvert;

    @Resource
    private MailService mailService;

    @Resource
    private UserSmsService smsService;

    @Autowired
    private UserOrgBusinessService userOrgBusinessService;

    @Resource
    private UserUserRoleService userUserRoleService;

    @Resource
    private UserService userService;

    @Resource
    private UserSmtpService userSmtpService;

    @Resource
    private RoleService roleService;

    @Resource
    private UserSmsService userSmsService;

    @Resource
    private UserAuthService userAuthService;

    @Resource
    private OrganizationQuotainfoService organizationQuotainfoService;

    @Resource
    private PackageGrpcService packageGrpcService;

    @Resource
    private SettingProperties settingProperties;

    @Resource
    private UserPlatformGrpcService userPlatformGrpcService;

    @Resource
    private UserUtil userUtil;

    @Resource
    private UserMfaSettingService userMfaSettingService;

    @Resource
    private UserBpDeliverGrpcService userBpDeliverGrpcService;

    //@Resource
    //private OrganizationMessageSender organizationMessageSender;

    @Resource
    private UserBusinessService userBusinessService;

    @Autowired
    private OmUserGrpcService omUserGrpcService;

    @Resource
    private UserOperateLogGrpcClientService userOperateLogGrpcClientService;

    @Resource
    private BpProjectGrpcService bpProjectGrpcService;

    @Resource
    private XunFeiYunProperties xunFeiYunProperties;

    /*@Resource
    private OssService ossService;*/

    @Autowired
    private StorageService storageService;

    //@Resource
    //private UserMessageSender userMessageSender;

    private String getEmailOssPath() {
        //return ossService.getUrlPrefix() + "email/";
        return storageService.getPropertiesValueBy(null, "domain") + storageService.getPropertiesValueBy(null, "base-path") + "email/";
    }

    /**
     * 获取公司全部信息
     *
     * @param corpCode  公司编码
     * @param ipAddress ip地址
     * @return company信息
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @date 2022/03/01 15:30
     */
    @Override
    public ServiceResult<CompanyDTO> getCompanyInfo(String ipAddress, String corpCode) {
        // 参数校验
        if (StringUtils.isBlank(ipAddress)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "ipAddress 不存在");
        }
        // 构建返回值
        CompanyDTO companyDTO = new CompanyDTO();

        // 根据orgCode和激活状态获取org信息
        OrganizationDO organizationDO = new OrganizationDO();
        organizationDO.setCode(corpCode);
        organizationDO.setStatus(OrganizationStatusEnum.ACTIVATED.getStatus());
        List<OrganizationDO> organizationDOS = organizationDao.selectBySelective(organizationDO);
        if (CollectionUtils.isEmpty(organizationDOS)) {
            return ServiceResult.fail(AuthErrorCodeEnum.ORG_NOT_EXISTS, String.format("organization[code=%s] not exist.", corpCode));
        }
        OrganizationDO orgInfo = organizationDOS.get(0);

        // 获取industry信息、销售邮箱、电话
        IndustryInfoDTO industryInfo = new IndustryInfoDTO();
        // 默认销售手机号，读取配置文件
        String contact = settingProperties.getDefaultMobile();
        IndustryDTO industryDTO = userAuthService.getIndustryAndContacts(ipAddress, orgInfo.getIndustryId());
        if (Objects.nonNull(industryDTO)) {
            if (Objects.nonNull(industryDTO.getCode())) {
                industryInfo.setCode(Integer.parseInt(industryDTO.getCode()));
            }
            industryInfo.setName(industryDTO.getName());
            industryInfo.setId(industryDTO.getIndustryId());
            if (CollectionUtils.isNotEmpty(industryDTO.getContacts())) {
                contact = industryDTO.getContacts().get(0);
            }
        }

        // 获取套餐信息，为空不报错
        PackageDTO packageDTO = packageGrpcService.getById(orgInfo.getPackageId());
        if (Objects.isNull(packageDTO)) {
            packageDTO = new PackageDTO();
        }

        boolean footerEdit = PackageEditionEnum.PACK_EDITION_ENTERPRISE.getType().equals(packageDTO.getEdition())
                && !OrgFooterEnum.ORGANIZATION_FOOTER_ALL.getType().equals(orgInfo.getFooter());

        // 根据公司id获取当前使用的套餐
        OrgPackInfoDTO orgPackInfoDTO = new OrgPackInfoDTO();
        JSONObject packageQuota = packageGrpcService.getPackageQuota(orgInfo.getPackageId(), null);
        JSONObject packPeram = new JSONObject();
        if (Objects.nonNull(packageQuota) && Objects.nonNull(packageQuota.getJSONObject("pack_perm"))) {
            packPeram = packageQuota.getJSONObject("pack_perm");

        }
        orgPackInfoDTO.setPackPeram(packPeram);
        orgPackInfoDTO.setSurveyQuota(Objects.isNull(packageDTO.getSurveyQuota()) ? 0 : packageDTO.getSurveyQuota());
        orgPackInfoDTO.setProjectQuota(Objects.isNull(packageDTO.getProjectQuota()) ? 0 : packageDTO.getProjectQuota());
        orgPackInfoDTO.setUserQuota(Objects.isNull(packageDTO.getUserQuota()) ? 0 : packageDTO.getUserQuota());
        orgPackInfoDTO.setMemberIndividuQuota(Objects.isNull(packageDTO.getMemberIndividuQuota()) ? 0 : packageDTO.getMemberIndividuQuota());
        orgPackInfoDTO.setMemberGroupQuota(Objects.isNull(packageDTO.getMemberGroupQuota()) ? -1 : packageDTO.getMemberGroupQuota());
        orgPackInfoDTO.setBiDatasourceQuota(Objects.isNull(packageDTO.getBiDatasourceQuota()) ? 0 : packageDTO.getBiDatasourceQuota());

        // 根据公司id获取租户的配额累计数信息
        ServiceResult<OrganizationQuotainfoDTO> quotainfoResult = organizationQuotainfoService.getByOrgId(orgInfo.getOrgId());
        OrgQuotaInfoDTO orgQuotaInfo = new OrgQuotaInfoDTO();
        orgQuotaInfo.setRespondentUsage(quotainfoResult.getData().getRespondentTotal());
        orgQuotaInfo.setProjectUsage(quotainfoResult.getData().getProjectTotal());
        orgQuotaInfo.setUserUsage(quotainfoResult.getData().getUserTotal());
        orgQuotaInfo.setMemberIndUsage(quotainfoResult.getData().getMemberIndTotal());
        orgQuotaInfo.setDatasourceUsage(quotainfoResult.getData().getDatasourceTotal());

        companyDTO.setContactsMobile("");
        companyDTO.setContactsEmail("");
        companyDTO.setContactsQrcode("");
        companyDTO.setPlatformUrl("");
        if (orgInfo.getSource().equals(OrgSourceEnum.OPENPLATFORM.getType())) {
            UserPlatformDTO userPlatformDTO = userPlatformGrpcService.selectByPlatformCode(orgInfo.getSourceRemark());
            if (Objects.nonNull(userPlatformDTO)) {
                companyDTO.setContactsMobile(userPlatformDTO.getContactsPhone());
                companyDTO.setContactsEmail(userPlatformDTO.getContactsEmail());
                companyDTO.setContactsQrcode(userPlatformDTO.getContactsQrcode());
                companyDTO.setPlatformUrl(userPlatformDTO.getUrl());
            }
        }

        Boolean userReach = orgPackInfoDTO.getUserQuota() >= 0 && orgQuotaInfo.getUserUsage() >= orgPackInfoDTO.getUserQuota();
        Boolean respondentReach = orgPackInfoDTO.getSurveyQuota() >= 0 && orgQuotaInfo.getRespondentUsage() >= orgPackInfoDTO.getSurveyQuota();
        Boolean projectReach = orgPackInfoDTO.getProjectQuota() >= 0 && orgQuotaInfo.getProjectUsage() >= orgPackInfoDTO.getProjectQuota();
        Boolean memberIndReach = orgPackInfoDTO.getMemberIndividuQuota() >= 0 && orgQuotaInfo.getMemberIndUsage() >= orgPackInfoDTO.getMemberIndividuQuota();
        Boolean trialFlag = StringUtils.isNotBlank(orgInfo.getTrialPackageId()) && orgInfo.getTrialPackageId().equals(orgInfo.getPackageId());

        // 设置返回值
        companyDTO.setCode(orgInfo.getCode());
        companyDTO.setName(orgInfo.getName());
        companyDTO.setStatus(orgInfo.getStatus());
        companyDTO.setPackageExpireTime(orgInfo.getPackageExpireTime());
        companyDTO.setFreeExpireTime(orgInfo.getFreeExpireTime());
        companyDTO.setSkin(orgInfo.getSkin());
        companyDTO.setPublicKey(orgInfo.getPublicKeyFilePath());
        companyDTO.setPackEdition(packageDTO.getEdition());
        companyDTO.setCompleteFlag(orgInfo.getCompleteFlag());
        companyDTO.setEmail(orgInfo.getAdminEmail());
        companyDTO.setOrgName(orgInfo.getName());
        companyDTO.setContact(contact);
        companyDTO.setFooterEdit(footerEdit);
        companyDTO.setIndustry(industryInfo);
        companyDTO.setSettingsIsXm(settingProperties.getIsXm());
        companyDTO.setSettingsNpShow(settingProperties.getNpShow());
        companyDTO.setCreateTime(orgInfo.getCreateTime());
        companyDTO.setPassConf(orgInfo.getPaasConf());
        companyDTO.setOrgId(orgInfo.getOrgId());
        List<String> unnetList = Lists.newArrayList("cem-unnet", "cem-unnet-snet");
        companyDTO.setUnNet(unnetList.contains(settingProperties.getPlatform()));
        companyDTO.setSource(orgInfo.getSource());
        companyDTO.setPackPerm(orgPackInfoDTO);
        companyDTO.setQuotainfo(orgQuotaInfo);
        companyDTO.setPackOutName(packageDTO.getOutName());
        companyDTO.setPackType(packageDTO.getType());
        companyDTO.setPackAdDisplay(packageDTO.getAdDisplay());
        companyDTO.setPackNavigationDisplay(packageDTO.getNavigationDisplay());
        companyDTO.setUserReach(userReach);
        companyDTO.setRespondentReach(respondentReach);
        companyDTO.setProjectReach(projectReach);
        companyDTO.setMemberIndReach(memberIndReach);
        companyDTO.setTrialFlag(trialFlag);
        // 获取mfa信息
        ServiceResult<UserMfaSettingDTO> mfaSettingByOrgId = userMfaSettingService.getMfaSettingByOrgId(orgInfo.getOrgId());
        UserMfaSettingDTO mfaSettingDto = mfaSettingByOrgId.getData();
        if (Objects.nonNull(mfaSettingDto)) {
            companyDTO.setOpenMfa(BooleanStatusEnum.toBoolean(mfaSettingDto.getOpenMfa()));
        }
        OrgCustomSettingInfoDTO customSetting = CustomSettingThreadLocalUtil.getCustomSetting();
        if (StringUtils.isNotEmpty(orgInfo.getCode()) && Objects.nonNull(customSetting)
                && orgInfo.getCode().equals(customSetting.getOrgCode())) {
            companyDTO.setCustomSetting(customSetting);
        }
        // 是否开启语音答题
        boolean openSpeechAnswer = !Lists.newArrayList("cem-unnet", "cem-unnet-snet").contains(settingProperties.getPlatform());
        if (openSpeechAnswer) {
            openSpeechAnswer = Stream.of(xunFeiYunProperties.getIatApiSecret(), xunFeiYunProperties.getIatAppId(),
                    xunFeiYunProperties.getIatApiKey(), xunFeiYunProperties.getIatApiSecret()).noneMatch(Objects::isNull);
        }
        companyDTO.setOpenSpeechAnswer(openSpeechAnswer);
        companyDTO.setScenarioId(orgInfo.getScenarioId());
        return ServiceResult.success(companyDTO);
    }

    @Override
    public ServiceResult<OrganizationDTO> selectByOrgCode(String orgCode) {
        if (StringUtils.isBlank(orgCode)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "orgCode不能为空！");
        }
        OrganizationDO organizationDO = organizationDao.selectByOrgCode(orgCode);
        return ServiceResult.success(organizationConvert.doToDto(organizationDO));
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> selectByIdsAndStatus(List<String> orgIds, Integer status) {
        if (CollectionUtils.isEmpty(orgIds)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id列表不能为空");
        }
        List<OrganizationDO> organizations = organizationDao.selectByIdsAndStatus(orgIds, status);
        return ServiceResult.success(organizationConvert.dosToDtos(organizations));
    }

    @Override
    public ServiceResult<String> insert(OrganizationDTO organizationDTO) {
        // 校验参数
        if (organizationDTO == null) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "参数为空");
        }
        // 新增
        String orgId = organizationDao.insertSelective(organizationConvert.dtoToDo(organizationDTO));
        // 设置返回值
        organizationDTO.setOrgId(orgId);
        return ServiceResult.success(orgId);
    }

    @Override
    public ServiceResult<List<String>> selectOrgCodesByIds(List<String> orgIds) {
        if (CollectionUtils.isEmpty(orgIds)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id列表为空");
        }

        return ServiceResult.success(organizationDao.selectOrgCodesByIds(orgIds));
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> selectByOrgIds(Set<String> orgIdSet) {
        if (CollectionUtils.isEmpty(orgIdSet)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id列表为空");
        }
        return ServiceResult.success(organizationConvert.dosToDtos(organizationDao.selectByOrgIds(orgIdSet)));
    }

    @Override
    public List<OrganizationDTO> getByfomalExpiryTime(LocalDateTime currentTime, List<Integer> status) {
        LocalDateTime time = currentTime.plusDays(30);
        List<OrganizationDO> organizationDOS = organizationDao.getByfomalExpiryTime(time, status);
        return organizationConvert.dosToDtos(organizationDOS);
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> getExpirePackOrg(String packType) {
        List<Integer> orgStatusList = Arrays.asList(OrganizationStatusEnum.ACTIVATED.getStatus(),
                OrganizationStatusEnum.EXPIRED.getStatus(),
                OrganizationStatusEnum.INACTIVATED.getStatus());

        List<OrganizationDO> list = organizationDao.getExpirePackOrg(packType, orgStatusList);
        return ServiceResult.success(organizationConvert.dosToDtos(list));
    }

    @Override
    public ServiceResult<OrganizationDTO> selectByIdAndStatus(String orgId, Integer status) {
        if (!ObjectId.isValid(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_FORMAT, "org_id格式错误!");
        }
        OrganizationDO organization = organizationDao.getOrgInfo(orgId, status);
        return ServiceResult.success(organizationConvert.doToDto(organization));
    }

    @Override
    public ServiceResult<OrganizationDTO> selectByCodeAndStatus(String orgCode, Integer status) {
        if (StringUtils.isBlank(orgCode) || Objects.isNull(status)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "orgCode和status都不能为空!");
        }
        OrganizationDO param = new OrganizationDO();
        param.setCode(orgCode);
        param.setStatus(status);
        List<OrganizationDO> organizationDos = organizationDao.selectBySelective(param);
        if (CollectionUtils.isEmpty(organizationDos)) {
            return ServiceResult.success();
        }
        return ServiceResult.success(organizationConvert.doToDto(organizationDos.get(0)));
    }

    /**
     * 根据id更新Organization
     *
     * @param organizationDTO 可选参数
     * @return com.bestcem.xm.util.ServiceResult<java.lang.Boolean>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/2 18:12
     */
    @Override
    public ServiceResult<Boolean> updateByPrimaryKeySelective(OrganizationDTO organizationDTO) {
        return ServiceResult.success(organizationDao.updateByPrimaryKeySelective(organizationConvert.dtoToDo(organizationDTO)));
    }


    @Override
    public ServiceResult<Boolean> updateByPrimaryKey(OrganizationDTO organizationDTO) {
        return ServiceResult.success(organizationDao.updateByPrimaryKey(organizationConvert.dtoToDo(organizationDTO)));
    }

    /**
     * 根据orgId获取Organization
     *
     * @param orgId 公司Id
     * @return com.bestcem.xm.util.ServiceResult<java.lang.Boolean>
     * @author jishuo <jishuo.yan@idiaoyan.com>
     * @date 2022/3/2 18:12
     */
    @Override
    public ServiceResult<OrganizationDTO> selectByPrimaryKey(String orgId) {
        if (!ObjectId.isValid(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_FORMAT, "org_id格式不正确");
        }
        return ServiceResult.success(organizationConvert.doToDto(organizationDao.selectByPrimaryKey(orgId)));
    }

    /**
     * 修改公司基础信息
     *
     * @param orgId                公司id
     * @param userId               用户id
     * @param updateOrgBaseInfoDTO 需要更新的公司基础信息
     * @return 公司信息
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @author yun.pan <yun.pan@idiaoyan.com>
     * @date 2022/03/02 15:30
     */
    @Override
    public ServiceResult<String> updateUserOrgInfo(String orgId, String userId, UpdateOrgBaseInfoDTO updateOrgBaseInfoDTO) {
        OrganizationDO organizationDO = new OrganizationDO();
        String name = updateOrgBaseInfoDTO.getName();

        // 设置更新字段
        organizationDO.setName(name);
        organizationDO.setOrgId(orgId);
        organizationDO.setOperatorId(userId);
        if (StringUtils.isNotBlank(updateOrgBaseInfoDTO.getIndustryId())) {
            organizationDO.setIndustryId(updateOrgBaseInfoDTO.getIndustryId());
        }
        if (StringUtils.isNotBlank(updateOrgBaseInfoDTO.getPaasConf())) {
            organizationDO.setPaasConf(updateOrgBaseInfoDTO.getPaasConf());
        }
        if (Objects.nonNull(updateOrgBaseInfoDTO.getDeliverCheckFlag())) {
            organizationDO.setDeliverCheckFlag(updateOrgBaseInfoDTO.getDeliverCheckFlag());
        }
        // 更新公司信息
        Boolean result = organizationDao.updateByPrimaryKeySelective(organizationDO);
        if (result.equals(Boolean.FALSE)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NO_DATA, "更新失败");
        }
        return ServiceResult.success(orgId);
    }

    /**
     * 修改个性化设置(公司皮肤)
     *
     * @param token   token信息
     * @param skinDTO 皮肤参数
     * @return ServiceResult<String>
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @author yun.pan <yun.pan@idiaoyan.com>
     * @date 2022/03/02 15:30
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult<String> updateOrgSkin(TokenDTO token, SkinDTO skinDTO) {
        String orgId = token.getOrgId();
        String userId = token.getUserId();
        OrganizationDO org = organizationDao.selectByPrimaryKey(orgId);

        JSONObject orgSkin;
        if (StringUtils.isNotBlank(org.getSkin())) {
            orgSkin = JSON.parseObject(org.getSkin());
        } else {
            orgSkin = new JSONObject();
        }
        JSONObject skinDTOJson = (JSONObject) JSON.toJSON(skinDTO);
        Iterator<Map.Entry<String, Object>> skinDtoIterator = skinDTOJson.entrySet().iterator();
        while (skinDtoIterator.hasNext()) {
            Map.Entry<String, Object> next = skinDtoIterator.next();
            if (Objects.nonNull(next.getValue())) {
                orgSkin.put(next.getKey(), next.getValue());
            }
        }

        // 设置org信息
        OrganizationDO organization = new OrganizationDO();
        organization.setOrgId(orgId);
        //skinDTO转换成Json字符串格式
        String skin = JSON.toJSONString(orgSkin);
        organization.setSkin(skin);
        organization.setOperatorId(userId);
        // 更新公司皮肤
        Boolean result = organizationDao.updateByPrimaryKeySelective(organization);
        if (Boolean.FALSE.equals(result)) {
            return ServiceResult.fail("更新公司皮肤失败");
        }

        org = organizationDao.selectByPrimaryKey(orgId);
        orgSkin = JSON.parseObject(org.getSkin());
        Iterator<Map.Entry<String, Object>> orgSkinIterator = orgSkin.entrySet().iterator();

        JSONObject diff = new JSONObject();
        while (skinDtoIterator.hasNext()) {
            Map.Entry<String, Object> val = skinDtoIterator.next();
            Map.Entry<String, Object> oldVal = orgSkinIterator.next();
            if (!oldVal.getValue().equals(val.getValue())) {
                diff.put("skin." + val.getKey(), val.getValue());
            }
        }
        while (orgSkinIterator.hasNext()) {
            Map.Entry<String, Object> orgSkinItem = orgSkinIterator.next();
            if (!skinDTOJson.entrySet().contains(orgSkinItem)) {
                diff.put("skin" + orgSkinItem.getKey(), "");
            }
        }

        // 新增用户操作日志
        if (diff.size() != 0) {
            UserOperateLogDTO operateLogDTO = new UserOperateLogDTO();
            operateLogDTO.setUserId(userId);
            operateLogDTO.setCategory(UserOperateLogCategoryEnum.OPERATE_LOG_CATEGORY_ORGANIZATION.getType());
            operateLogDTO.setOperation(UserOperateLogOperationEnum.OPERATE_LOG_OPERATION_UPDATE_ORG.getType());
            operateLogDTO.setOperateeId(userId);
            operateLogDTO.setTargetId(orgId);
            operateLogDTO.setMsg(diff.toJSONString());
            Boolean operateLog = userOperateLogGrpcClientService.createOperateLog(operateLogDTO);
            if (Boolean.FALSE.equals(operateLog)) {
                return ServiceResult.fail("新增用户操作日志失败");
            }
        }

        //if (Boolean.FALSE.equals(skinDTO.getIpPrivacy())) {
        //    Boolean closeProjectIpAttr = bpProjectGrpcService.closeProjectIpAttr(orgId);
        //    if (Boolean.FALSE.equals(closeProjectIpAttr)) {
        //        return ServiceResult.fail("关闭租户下所有问卷IP配置失败");
        //    }
        //}

        return ServiceResult.success(orgId);
    }


    @Override
    public ServiceResult<Boolean> sendPackExpireSmsAndEmail(PackExpireEmailDTO expireEmailDTO) {
        String url = settingProperties.getSassServerUrl() + "/version";
        ServiceResult<OrganizationDTO> orgResutl = selectByOrgCode(expireEmailDTO.getCode());
        OrganizationDTO organizationDTO = orgResutl.getData();
        PackageDTO packageDTO = packageGrpcService.getById(expireEmailDTO.getFormalPackageId());
        // 获取系统管理员
        ServiceResult<UserDTO> adminUserResult = userBusinessService.getAdminUserByOrgId(expireEmailDTO.getOrgId());
        UserDTO userDTO = adminUserResult.getData();
        if (!"prod".equals(settingProperties.getAppEnv()) && !userUtil.checkUserIsInner(userDTO.getPhone(), userDTO.getEmail(), "")) {
            return ServiceResult.success(Boolean.TRUE);
        }
        if (Objects.nonNull(userDTO) && StringUtils.isNotBlank(userDTO.getPhone())) {
            Map<String, Object> map = new HashMap<>();
            map.put("mobile", userDTO.getPhone());
            map.put("name", userDTO.getName());
            map.put("pack_name", packageDTO.getOutName());
            map.put("pack_data", expireEmailDTO.getFormalExpireTime());
            map.put("url", url);
            map.put("type", "已于");
            map.put("time", DateUtil.convertDteToString(new Date(), DateUtil.YYYY_MM_DD));
            map.put("telephone", settingProperties.getBestHotline());
            map.put("org_code", organizationDTO.getCode());
            map.put("notify_title", "版本到期");
            map.put("org_id", organizationDTO.getOrgId());
            // 短信发送
            notifyTemporaryReminderBySms(userDTO.getPhone(), map);
        }

        if (Objects.nonNull(userDTO) && Objects.nonNull(packageDTO) && StringUtils.isNotBlank(userDTO.getEmail())) {
            Map<String, Object> emailMap = new HashMap<>();
            emailMap.put("email", userDTO.getEmail());
            emailMap.put("name", userDTO.getName());
            emailMap.put("org_code", organizationDTO.getCode());
            emailMap.put("org_name", organizationDTO.getName());
            emailMap.put("pack_name", packageDTO.getOutName());
            emailMap.put("pack_data", expireEmailDTO.getFormalExpireTime());
            emailMap.put("url", url);
            emailMap.put("type", "已于");
            emailMap.put("time", DateUtil.convertDteToString(new Date(), DateUtil.YYYY_MM_DD));
            emailMap.put("telephone", settingProperties.getBestHotline());
            emailMap.put("subject", "已");
            emailMap.put("org_id", organizationDTO.getOrgId());
            emailMap.put("email_oss_path", getEmailOssPath());
            // 邮件发送
            notifyTemporaryReminderByEmail(userDTO.getEmail(), emailMap);
        }

        RelationDTO orgRelatedOp = omUserGrpcService.getOrgRelatedOp(organizationDTO.getOrgId());
        if (Objects.nonNull(userDTO) && Objects.nonNull(packageDTO) && StringUtils.isNotBlank(orgRelatedOp.getId())) {
            OmUserDTO omUserDTO = omUserGrpcService.getOmUser(orgRelatedOp.getId());
            Map<String, Object> emailMap = new HashMap<>();
            emailMap.put("email", omUserDTO.getEmail());
            emailMap.put("name", userDTO.getName());
            emailMap.put("org_code", organizationDTO.getCode());
            emailMap.put("org_name", organizationDTO.getName());
            emailMap.put("pack_name", packageDTO.getOutName());
            emailMap.put("pack_data", expireEmailDTO);
            emailMap.put("url", url);
            emailMap.put("type", "已于");
            emailMap.put("time", new Date());
            emailMap.put("telephone", settingProperties.getBestHotline());
            emailMap.put("subject", "已");
            emailMap.put("org_id", organizationDTO.getOrgId());
            // 邮件发送
            notifyTemporaryReminderByEmail(omUserDTO.getEmail(), emailMap);
        }
        return ServiceResult.success(Boolean.TRUE);
    }

    @Override
    public ServiceResult<String> updateOrg(OrganizationDTO dto) {
        // 参数校验
        if (Objects.isNull(dto) || StringUtils.isEmpty(dto.getOrgId())) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "参数不能为空");
        }

        // 获取管理员角色Id
        ServiceResult<String> adminRole = roleService.getAdminRole(dto.getOrgId());
        if (!adminRole.isSuccess() || Objects.isNull(adminRole.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未找到该租户的管理员角色信息");
        }

        // 根据角色Id和组织查询不是禁用状态的用户id列表
        ServiceResult<List<String>> userIdsResult = userService.getUserIdsByRoleAndOrgAndStatus(adminRole.getData(), dto.getOrgId(),
                Lists.newArrayList(UserStatusEnum.ACTIVATED.getStatus(), UserStatusEnum.INACTIVATED.getStatus()));
        List<String> userIds = userIdsResult.getData();
        // 如果修改邮箱，则判断邮箱是否有其他子账号使用
        if (CollectionUtils.isNotEmpty(userIds) && StringUtils.isNotEmpty(dto.getAdminEmail())) {
            ServiceResult<List<UserDTO>> userInfoResult = userService.selectByOrgAndEmailAndUserIds(dto.getOrgId(), dto.getAdminEmail(), userIds);
            if (CollectionUtils.isNotEmpty(userInfoResult.getData())) {
                return ServiceResult.fail(ResourceErrorCodeEnum.DUPLICATE, "邮箱在该租户中已存在");
            }
        }
        // 如果修改管理员手机号，则判断手机号是否有其他子账号使用
        if (CollectionUtils.isNotEmpty(userIds) && StringUtils.isNotEmpty(dto.getAdminPhone())) {
            ServiceResult<List<UserDTO>> userInfoResult = userService.selectByOrgAndPhonePhoneAndUserIds(dto.getOrgId(), dto.getAdminPhone(), userIds);
            if (CollectionUtils.isNotEmpty(userInfoResult.getData())) {
                return ServiceResult.fail(ResourceErrorCodeEnum.DUPLICATE, "手机号在该租户中已存在");
            }
        }

        // 获取旧公司数据信息
        OrganizationDO oldOrg = organizationDao.selectByPrimaryKey(dto.getOrgId());
        if (Objects.isNull(oldOrg)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到orgId对应的租户信息！");
        }

        // 处理其他字段赋值信息
        if (StringUtils.isNotEmpty(dto.getPackageId())) {
            dto.setFormalPackageId(dto.getPackageId());
        }
        if (Objects.nonNull(dto.getPackageExpireTime())) {
            dto.setFormalExpireTime(dto.getPackageExpireTime());
        }
        if (StringUtils.isNotEmpty(dto.getCode())) {
            dto.setCode(dto.getCode().toLowerCase());
            // 校验code信息
            ServiceResult<String> checkOrgCode = userOrgBusinessService.checkOrgCode(dto.getCode());
            if (!checkOrgCode.isSuccess()) {
                return ServiceResult.fail(ReqErrorCodeEnum.PARAM_FORMAT, "code 格式错误");
            }
        }
        // 校验短信单价
        if (Objects.nonNull(dto.getSmsPrice()) && dto.getSmsPrice() > SMS_PRICE_MAX) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_RANGE, "The sms_price must lte" + SMS_PRICE_MAX);
        }
        if (Objects.nonNull(dto.getSmsPrice()) && dto.getSmsPrice() < SMS_PRICE_MIN) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_RANGE, "The sms_price must lte" + SMS_PRICE_MIN);
        }
        if (StringUtils.isNotEmpty(dto.getFormalPackageId())) {
            dto.setPackageId(dto.getFormalPackageId());
            dto.setPackageExpireTime(dto.getFormalExpireTime());
        }
        if (StringUtils.isNotEmpty(dto.getTrialPackageId())) {
            dto.setPackageId(dto.getTrialPackageId());
            dto.setPackageExpireTime(dto.getTrialExpireTime());
        }
        if (StringUtils.isNotEmpty(dto.getContractUrls())) {
            dto.setContractUrls(dto.getContractUrls());
        }

        // 如果公司修改了orgCode或者orgName，则需要发送mq通知
        //if (!oldOrg.getCode().equals(dto.getCode()) || !oldOrg.getName().equals(dto.getName())) {
        //    organizationMessageSender.orgInfoUpdate(dto.getOrgId(), dto.getName(), dto.getCode());
        //}

        // 更新租户信息
        Boolean updateOrgResult;
        if (Boolean.TRUE.equals(dto.getBackend())) {
            OrganizationDTO newDTO = createNewOrgDTO(oldOrg, dto);
            updateOrgResult = organizationDao.updateByPrimaryKey(organizationConvert.dtoToDo(newDTO));
        } else {
            updateOrgResult = organizationDao.updateByPrimaryKeySelective(organizationConvert.dtoToDo(dto));
        }
        if (!Boolean.TRUE.equals(updateOrgResult)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.UPDATE_FORBID, "更新租户信息失败");
        }
        // 更新成功,若使用的套餐版本变更则发送mq消息
        //if (StringUtils.isNotBlank(dto.getPackageId()) && !dto.getPackageId().equals(oldOrg.getPackageId())) {
        //    organizationMessageSender.orgPackUpdate(dto.getOrgId(), oldOrg.getPackageId(), dto.getPackageId());
        //}
        UserDTO adminUser = new UserDTO();
        UserBookingDTO userBookingDTO = new UserBookingDTO();
        userBookingDTO.setOrgId(dto.getOrgId());
        boolean updateAdminUser = false;
        if (StringUtils.isNotEmpty(dto.getName())) {
            userBookingDTO.setCompanyName(dto.getName());
        }
        if (StringUtils.isNotEmpty(dto.getAdminEmail())) {
            adminUser.setEmail(dto.getAdminEmail());
            updateAdminUser = true;
            userBookingDTO.setEmail(dto.getAdminEmail());
        }
        if (StringUtils.isNotEmpty(dto.getAdminPhone())) {
            adminUser.setPhone(dto.getAdminPhone());
            updateAdminUser = true;
            userBookingDTO.setPhone(dto.getAdminPhone());
        }
        if (StringUtils.isNotEmpty(dto.getIndustryId())) {
            userBookingDTO.setIndustryId(dto.getIndustryId());
        }

        // 更新管理员邮箱和手机号
        if (updateAdminUser) {
            userService.updateByUserIds(userIds, adminUser);
            //userMessageSender.publishUserUpdateContacts(null, userIds, adminUser.getUserName(), adminUser.getPhone(), adminUser.getEmail());
        }

        // 更新公司预约信息
        omUserGrpcService.updateBookingByOrgId(userBookingDTO);
        // 删除套餐缓存
        packageGrpcService.deletePackageCacheByOrgId(dto.getOrgId());
        return ServiceResult.success();
    }

    private OrganizationDTO createNewOrgDTO(OrganizationDO oldOrg, OrganizationDTO dto) {
        OrganizationDTO newDTO = organizationConvert.doToDto(oldOrg);
        newDTO.setCode(dto.getCode());
        newDTO.setName(dto.getName());
        newDTO.setCreatorId(dto.getCreatorId());
        newDTO.setOperatorId(dto.getOperatorId());
        newDTO.setContent(dto.getContent());
        newDTO.setUpdateTime(new Date());
        newDTO.setIndustryId(dto.getIndustryId());
        newDTO.setAdminEmail(dto.getAdminEmail());
        newDTO.setAdminPhone(dto.getAdminPhone());
        newDTO.setAdminName(dto.getAdminName());
        newDTO.setSource(dto.getSource());
        newDTO.setSourceRemark(dto.getSourceRemark());
        newDTO.setPackageId(dto.getPackageId());
        newDTO.setPackageExpireTime(dto.getPackageExpireTime());
        newDTO.setFormalPackageId(dto.getFormalPackageId());
        newDTO.setFormalExpireTime(dto.getFormalExpireTime());
        newDTO.setFreeExpireTime(dto.getFreeExpireTime());
        newDTO.setStatus(dto.getStatus());
        newDTO.setTrialPackageId(dto.getTrialPackageId());
        newDTO.setTrialExpireTime(dto.getTrialExpireTime());
        newDTO.setBanLoginTrialExpiration(dto.getBanLoginTrialExpiration());
        newDTO.setSmsPrice(dto.getSmsPrice());
        newDTO.setFooter(dto.getFooter());
        newDTO.setInnerFlag(dto.getInnerFlag());
        newDTO.setDeliveryAuthType(dto.getDeliveryAuthType());
        newDTO.setContractUrls(dto.getContractUrls());
        newDTO.setSensitiveWordEnable(dto.getSensitiveWordEnable());
        return newDTO;
    }

    @Override
    public ServiceResult<CheckPreferenceDTO> getCheckPreferenceInfo(String orgId) {
        // 参数校验
        if (StringUtils.isBlank(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id不能为空");
        }

        // 查询公司信息
        OrganizationDO organizationDO = organizationDao.selectByPrimaryKey(orgId);
        if (Objects.isNull(organizationDO)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到对应的公司信息");
        }

        CheckPreferenceDTO dto = new CheckPreferenceDTO();
        dto.setCheckDeliver(organizationDO.getDeliverCheckFlag());
        dto.setCheckSmtpId(organizationDO.getCheckSmtpId());

        // 获取系统内置的投放审核角色
        ServiceResult<String> deliverCheckRole = roleService.getDeliverCheckRole(orgId);
        if (deliverCheckRole.isSuccess() && StringUtils.isNotBlank(deliverCheckRole.getData())) {
            String roleId = deliverCheckRole.getData();
            List<String> userIds = userUserRoleService.listUserIdsByRoleId(roleId).getData();
            if (CollectionUtils.isNotEmpty(userIds)) {
                // 根据userIds查询用户信息列表
                ServiceResult<List<UserDTO>> users = userService.selectByIds(userIds);
                List<UserDTO> data = users.getData();
                for (UserDTO datum : data) {
                    datum.setPassword("");
                    datum.setSalt("");
                }
                dto.setCheckUsers(data);
            }
        }

        return ServiceResult.success(dto);
    }

    @Override
    public ServiceResult<Boolean> saveCheckPreferenceInfo(String orgId, Integer checkDeliver, String checkSmtpId,
                                                          List<String> userId, String opreateUserId) {
        // 参数校验
        if (StringUtils.isBlank(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id不能为空");
        }
        // 查询公司信息
        OrganizationDO organizationDO = organizationDao.selectByPrimaryKey(orgId);
        if (Objects.isNull(organizationDO)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到对应的公司信息");
        }

        // 获取系统内置的投放审核角色
        ServiceResult<String> deliverCheckRole = roleService.getDeliverCheckRole(orgId);
        if (deliverCheckRole.isSuccess() && StringUtils.isNotBlank(deliverCheckRole.getData())) {
            String roleId = deliverCheckRole.getData();
            List<String> userIds = userUserRoleService.listUserIdsByRoleId(roleId).getData();
            if (!checkDeliver.equals(organizationDO.getDeliverCheckFlag()) || !checkDiffrent(userIds, userId)) {
                Boolean checkResult = userBpDeliverGrpcService.checkOrgHasUnfinishDeliver(orgId);
                if (Boolean.FALSE.equals(checkResult)) {
                    return ServiceResult.fail(ResourceErrorCodeEnum.STATUS_CHANGED, "有投放尚未完成，不能设置审核属性");
                }
                // 设置投放审核用户
                userUserRoleService.updateRoleUsers(orgId, roleId, userId, opreateUserId);
            }
        }

        // 更新发件箱
        String updateCheckSmtpId = "";
        if (StringUtils.isNotBlank(checkSmtpId) && !checkSmtpId.equals(organizationDO.getCheckSmtpId())) {
            // 校验发件箱是否有效
            ServiceResult<UserSmtpDTO> userSmtpDTOServiceResult = userSmtpService.selectByIdAndOrgId(checkSmtpId, orgId);
            if (userSmtpDTOServiceResult.isSuccess() && Objects.nonNull(userSmtpDTOServiceResult.getData())) {
                updateCheckSmtpId = checkSmtpId;
            }
        }
        organizationDO = new OrganizationDO();
        organizationDO.setOrgId(orgId);
        organizationDO.setCheckSmtpId(updateCheckSmtpId);
        organizationDO.setDeliverCheckFlag(checkDeliver);
        organizationDO.setOperatorId(opreateUserId);
        organizationDao.updateByPrimaryKeySelective(organizationDO);
        return ServiceResult.success();
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> selectBySelective(OrganizationDTO organizationDTO) {
        List<OrganizationDO> organizationDOS = organizationDao.selectBySelective(organizationConvert.dtoToDo(organizationDTO));
        return ServiceResult.success(organizationConvert.dosToDtos(organizationDOS));
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> getAllOrg() {
        List<OrganizationDTO> organizationDTOS = organizationConvert.dosToDtos(organizationDao.getAllOrg());
        return ServiceResult.success(organizationDTOS);
    }

    @Override
    public ServiceResult<PageResponseDTO<OrganizationDTO>> listOrganizationsByPage(ListOrgByPageParam param) {
        ListOrgByPageDO pageDO = new ListOrgByPageDO();
        pageDO.setSearch(param.getSearch());
        pageDO.setPage((param.getPageParam().getOffset()));
        pageDO.setSize(param.getPageParam().getSize());
        if (Objects.nonNull(param.getTimeFilter()) && StringUtils.isNotBlank(param.getStartTime()) && StringUtils.isNotBlank(param.getEndTime())) {
            pageDO.setStartTime(DateUtil.getDate(param.getStartTime()));
            pageDO.setEndTime(DateUtil.getDate(param.getEndTime()));
            if (param.getTimeFilter().equals(0)) {
                pageDO.setTimeFilterStr("formal_expire_time");
            }
            if (param.getTimeFilter().equals(1)) {
                pageDO.setTimeFilterStr("trial_expire_time");
            }
            if (param.getTimeFilter().equals(2)) {
                pageDO.setTimeFilterStr("create_time");
            }
        }
        if (CollectionUtils.isNotEmpty(param.getOrgIdList())) {
            pageDO.setOrgIdList(param.getOrgIdList());
        }
        if (CollectionUtils.isNotEmpty(param.getIndustryIdList())) {
            pageDO.setIndustryIdList(param.getIndustryIdList());
        }
        pageDO.setStatusList(param.getStatuses());
        Long count = Long.valueOf(organizationDao.listOrganizationsByPageCount(pageDO, organizationConvert.dtoToDo(param.getOrganizationDTO())));
        if (count == 0L) {
            return ServiceResult.success(new PageResponseDTO<>(new ArrayList<>(), count, param.getPageParam().getPage()));
        }
        List<OrganizationDO> organizationList = organizationDao.listOrganizationsByPage(pageDO, organizationConvert.dtoToDo(param.getOrganizationDTO()));
        List<OrganizationDTO> organizationDTOList = organizationConvert.dosToDtos(organizationList);
        return ServiceResult.success(new PageResponseDTO<>(organizationDTOList, count, param.getPageParam().getPage()));
    }

    @Override
    public ServiceResult<List<String>> selectOrgIdsByPackageIds(List<String> packageIdsList) {
        if (CollectionUtils.isEmpty(packageIdsList)) {
            return ServiceResult.fail("packageIdsList为空");
        }
        return ServiceResult.success(organizationDao.selectOrgIdsByPackageIds(packageIdsList));
    }

    /**
     * 判断两个list内容是否完全一样
     *
     * @param list  集合1
     * @param list1 集合2
     * @return boolean
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/03/17 11:22
     */
    private static boolean checkDiffrent(List<String> list, List<String> list1) {
        list.sort(Comparator.comparing(String::hashCode));
        list1.sort(Comparator.comparing(String::hashCode));
        return list.toString().equals(list1.toString());
    }


    @Override
    public ServiceResult<Boolean> updateInitFreeOrg() {
        organizationDao.updateCompleteFlag(OrgCompleteFlagEnum.COMPLETE.getType(), OrgCompleteFlagEnum.NO_COMPLETE.getType());
        // 当天0点
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date expireDate = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        // 昨天0点
        Date yesterday = calendar.getTime();
        organizationDao.updatePackGteTodayOrg(OrganizationStatusEnum.INACTIVATED.getStatus(), OrganizationStatusEnum.EXPIRED.getStatus(), expireDate, yesterday);
        organizationDao.updatePackLteTodayOrg(OrganizationStatusEnum.INACTIVATED.getStatus(), OrganizationStatusEnum.EXPIRED.getStatus(), expireDate);
        return ServiceResult.success(Boolean.TRUE);
    }


    @Override
    public ServiceResult<Boolean> notifyTemporaryReminderBySms(String phone, Map<String, Object> map) {

        // 解析短信发送模版
        String smsContent = StringFormatUtil.format(SmsConstant.PACKAGE_TEMPORARY_SMS_TEMPLE, map);
        String param = JSON.toJSONString(map);
        Integer status = null;
        try {
            userSmsService.sendSms(phone, smsContent);
            status = NotifyStatusEnum.IS_SEND.getType();
        } catch (Exception e) {
            log.error(String.format("send notify_company_package_upgrade_by_sms error: %s", e));
            status = NotifyStatusEnum.SEND_FAILED.getType();
        } finally {
            RecordToOmDTO recordToOmDTO = new RecordToOmDTO();
            recordToOmDTO.setContent(smsContent);
            recordToOmDTO.setName(map.get("notify_title") != null ? map.get("notify_title").toString() : "");
            recordToOmDTO.setOrgId(map.get("org_id") != null ? map.get("org_id").toString() : "");
            recordToOmDTO.setReceiver(phone);
            recordToOmDTO.setSender("");
            recordToOmDTO.setType(NotifyTypeEnum.MOBILE.getType());
            recordToOmDTO.setSmsChannel(NotifySmsChannelEnum.YIMEI.getType());
            recordToOmDTO.setStatus(status);
            recordToOmDTO.setSendTime(DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
            recordToOmDTO.setTemplateId("");
            recordToOmDTO.setParams(param);
            userUtil.recordToOm(recordToOmDTO);
        }
        return ServiceResult.success(Boolean.TRUE);
    }

    @Override
    public ServiceResult<Boolean> notifyTemporaryReminderByEmail(String email, Map<String, Object> emailMap) {
        String[] sender = new String[]{email};
        String subject = settingProperties.getBestcemEmailSign() + "套餐" + emailMap.get("subject") + "过期";
        String tmpl = EmailTemplateEnum.PACKAGE_TEMPLATE.getFileName();

        HashMap<String, Object> map = new HashMap<>();
        map.put("name", emailMap.get("name"));
        map.put("org_code", emailMap.get("org_code"));
        map.put("org_id", emailMap.get("org_id"));
        map.put("org_name", emailMap.get("org_name"));
        map.put("pack_name", emailMap.get("pack_name"));
        map.put("type", emailMap.get("type"));
        map.put("pack_data", emailMap.get("pack_data"));
        map.put("telephone", emailMap.get("telephone"));
        map.put("url", emailMap.get("url"));
        map.put("time", emailMap.get("time"));
        map.put("email_oss_path", emailMap.get("email_oss_path"));
        map.put("notify_title", emailMap.get("notify_title"));
        mailService.emailSendAndNotifyOm(sender, null, subject, tmpl, map);
        return ServiceResult.success(Boolean.TRUE);
    }

    @Override
    public ServiceResult<Boolean> notifyTestTemporaryReminderByEmail(List<String> emails, Map<String, Object> emailMap) {
        String[] sender = emails.toArray(new String[emails.size()]);
        String subject = settingProperties.getBestcemEmailSign() + "套餐" + emailMap.get("subject") + "过期";
        String tmpl = EmailTemplateEnum.PACKAGE_TEMPLATE.getFileName();

        HashMap<String, Object> map = new HashMap<>();
        map.put("name", emailMap.get("name"));
        map.put("org_code", emailMap.get("org_code"));
        map.put("org_id", emailMap.get("org_id"));
        map.put("org_name", emailMap.get("org_name"));
        map.put("pack_name", emailMap.get("pack_name"));
        map.put("type", emailMap.get("type"));
        map.put("pack_data", emailMap.get("pack_data"));
        map.put("telephone", emailMap.get("telephone"));
        map.put("url", emailMap.get("url"));
        map.put("time", emailMap.get("time"));
        map.put("email_oss_path", emailMap.get("email_oss_path"));

        mailService.sendEmail(sender, subject, tmpl, map);
        return ServiceResult.success(Boolean.TRUE);
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> listOrganizations(OrgConditionDTO orgConditionDTO, List<Integer> statuses, String search, List<String> fields, Integer limit) {
        // 去重并映射到表字段
        String tableFields = null;
        if (CollectionUtils.isNotEmpty(fields)) {
            Set<String> tempSet = new HashSet<>(fields);
            tableFields = tempSet.stream().map(CommonConstant.ORG_FIELD_MAP::get).filter(StringUtils::isNotBlank).collect(Collectors.joining(StrUtil.COMMA));
        }

        // 整合组织状态
        if (CollectionUtils.isEmpty(statuses)) {
            statuses = new ArrayList<>();
        }
        Integer status = orgConditionDTO.getStatus();
        if (Objects.nonNull(status) && !statuses.contains(status)) {
            statuses.add(status);
            orgConditionDTO.setStatus(null);
        }

        OrganizationDO organizationDO = OrgConditionConvert.dto2Do(orgConditionDTO);
        List<OrganizationDO> list = organizationDao.listOrganizations(organizationDO, statuses, search, tableFields, limit);
        if (Objects.isNull(list)) {
            ServiceResult.fail("【用户中心】根据搜索条件查询公司列表失败");
        }
        return ServiceResult.success(organizationConvert.dosToDtos(list));
    }

    @Override
    public ServiceResult<PageResponseDTO<OrganizationDTO>> listOrgsByPaging(OrgConditionDTO orgConditionDTO, ListOrgsByPagingParam param, Page page) {
        // 整合范围查询条件
        integrateRangeCondition(orgConditionDTO, param);

        // 分页
        int currentPage = page.getPage();
        int limit = page.getSize();
        int offset = PageUtil.getStart(currentPage, limit);

        // 查询租户总量
        OrganizationDO organizationDO = OrgConditionConvert.dto2Do(orgConditionDTO);
        Integer count = organizationDao.baseCount(organizationDO, param, limit, offset);
        if (Objects.isNull(count) || count.equals(0)) {
            return ServiceResult.success(new PageResponseDTO<>(Collections.emptyList(), 0L, currentPage));
        }

        // 去重并映射到表字段
        String tableFields = null;
        if (CollectionUtils.isNotEmpty(param.getFields())) {
            Set<String> tempSet = new HashSet<>(param.getFields());
            tableFields = tempSet.stream().map(CommonConstant.ORG_FIELD_MAP::get).filter(StringUtils::isNotBlank).collect(Collectors.joining(StrUtil.COMMA));
        }
        param.setTableFields(tableFields);

        // 查询公司列表
        List<OrganizationDO> list = organizationDao.listOrgsByPaging(organizationDO, param, limit, offset);
        if (Objects.isNull(list)) {
            ServiceResult.fail("【用户中心】根据搜索条件查询公司列表失败");
        }
        return ServiceResult.success(new PageResponseDTO<>(organizationConvert.dosToDtos(list), count.longValue(), currentPage));
    }

    /**
     * 整合范围查询条件
     *
     * @param orgConditionDTO 等于查询条件
     * @param param           范围查询条件
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 17:50 2022/8/19
     */
    private void integrateRangeCondition(OrgConditionDTO orgConditionDTO, ListOrgsByPagingParam param) {
        // 时间筛选
        Integer timeFilter = param.getTimeFilter();
        if (Objects.nonNull(timeFilter)) {
            if (OrgPackageTimeFilterEnum.FORMAL_EXPIRE.getType().equals(timeFilter)) {
                param.setTimeFilterStr(OrgPackageTimeFilterEnum.FORMAL_EXPIRE.getDesc());
            } else if (OrgPackageTimeFilterEnum.TRIAL_EXPIRE.getType().equals(timeFilter)) {
                param.setTimeFilterStr(OrgPackageTimeFilterEnum.TRIAL_EXPIRE.getDesc());
            } else if (OrgPackageTimeFilterEnum.CREATE_TIME.getType().equals(timeFilter)) {
                param.setTimeFilterStr(OrgPackageTimeFilterEnum.CREATE_TIME.getDesc());
            }
        }
        // 整合组织状态
        if (CollectionUtils.isEmpty(param.getStatuses())) {
            param.setStatuses(new ArrayList<>());
        }
        Integer status = orgConditionDTO.getStatus();
        if (Objects.nonNull(status) && !param.getStatuses().contains(status)) {
            param.getStatuses().add(status);
            orgConditionDTO.setStatus(null);
        }
        // 整合状态来源
        if (CollectionUtils.isEmpty(param.getSources())) {
            param.setSources(new ArrayList<>());
        }
        Integer source = orgConditionDTO.getSource();
        if (Objects.nonNull(source) && param.getSources().contains(source)) {
            param.getSources().add(source);
            orgConditionDTO.setSource(null);
        }
        // 整合状态来源详情
        if (CollectionUtils.isEmpty(param.getSourceRemarks())) {
            param.setSourceRemarks(new ArrayList<>());
        }
        String sourceRemark = orgConditionDTO.getSourceRemark();
        if (StringUtils.isNotBlank(sourceRemark) && param.getSourceRemarks().contains(sourceRemark)) {
            param.getSourceRemarks().add(sourceRemark);
            orgConditionDTO.setSourceRemark(null);
        }
        // 整合租户id
        if (CollectionUtils.isEmpty(param.getOrgIds())) {
            param.setOrgIds(new ArrayList<>());
        }
        String orgId = orgConditionDTO.getOrgId();
        if (StringUtils.isNotBlank(orgId) && !param.getOrgIds().contains(orgId)) {
            param.getOrgIds().add(orgId);
            orgConditionDTO.setOrgId(null);
        }
        // 整合industryId
        if (CollectionUtils.isEmpty(param.getIndustryIds())) {
            param.setIndustryIds(new ArrayList<>());
        }
        String industryId = orgConditionDTO.getIndustryId();
        if (StringUtils.isNotBlank(industryId) && !param.getIndustryIds().contains(industryId)) {
            param.getIndustryIds().add(industryId);
            orgConditionDTO.setIndustryId(null);
        }
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> listOrganizations(OrgConditionDTO orgConditionDTO, Integer limit) {
        return this.listOrganizations(orgConditionDTO, null, null, null, limit);
    }

    @Override
    public ServiceResult<PageResponseDTO<OrganizationDTO>> listOrgsByFilter(ListOrgsByFilterParam param) {
        ListOrgsByFilterDO pageDO = new ListOrgsByFilterDO();
        pageDO.setOffset((param.getPageParam().getOffset()));
        pageDO.setSize(param.getPageParam().getSize());
        pageDO.setStatusList(param.getStatusList());
        pageDO.setCodeList(param.getCodeList());
        pageDO.setSourceList(param.getSourceList());
        pageDO.setSourceRemarkList(param.getSourceRemarkList());
        Long count = organizationDao.listOrgsByFilterCount(pageDO);
        if (count == 0L) {
            return ServiceResult.success(new PageResponseDTO<>(new ArrayList<>(), count, param.getPageParam().getPage()));
        }
        List<OrganizationDO> organizationList = organizationDao.listOrgsByFilter(pageDO);
        List<OrganizationDTO> organizationDTOList = organizationConvert.dosToDtos(organizationList);
        return ServiceResult.success(new PageResponseDTO<>(organizationDTOList, count, param.getPageParam().getPage()));
    }

    @Override
    public ServiceResult<List<OrganizationDTO>> listByCodes(List<String> orgCodes) {
        // 校验参数
        if (CollectionUtils.isEmpty(orgCodes)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "org codes empty");
        }
        // 查询
        return ServiceResult.success(organizationConvert.dosToDtos(organizationDao.listByOrgCodes(orgCodes)));
    }

    @Override
    public void notifyCompanyAcceptByEmail(String email, Map<String, String> dataMap) {
        String subject = settingProperties.getBestcemEmailSign() + MailSubjectNotifyTitleEnumProperties.NotifyTitleEnum.REGISTER.getKey();
        String tmpl = EmailTemplateEnum.BOOK_NOTIFY_TEMPLATE.getFileName();
        HashMap<String, Object> data = new HashMap<>();
        data.put("code", dataMap.get("code"));
        data.put("userName", dataMap.get("userName"));
        data.put("companyName", dataMap.get("companyName"));
        data.put("corp_url", userUtil.getCorpUrl(dataMap.get("org_id"), dataMap.get("code"), "", "") + "/login");
        data.put("username", StringUtils.isBlank(dataMap.get("username")) ? "superadmin" : dataMap.get("username"));
        data.put("passwd", Objects.isNull(dataMap.get("passwd")) ? "123456" : dataMap.get("passwd"));
        data.put("hotline", Objects.isNull(dataMap.get("hotline")) ? CommonConstant.BEST_HOTLINE : dataMap.get("hotline"));
        data.put("expiry_date", dataMap.get("expiryDT"));
        data.put("today", DateUtil.convertDteToString(new Date(), DateUtil.YYYY_MM_DD));
        data.put("manager_mobile", dataMap.get("manager_mobile"));
        data.put("manager_email", dataMap.get("manager_email"));
        data.put("xm_name", CommonConstant.XM_NAME);
        //data.put("oss_url_prefix", ossService.getUrlPrefix());
        data.put("oss_url_prefix", storageService.getPropertiesValueBy(null, "domain") + storageService.getPropertiesValueBy(null, "base-path"));
        data.put("org_id", dataMap.get("org_id"));
        mailService.emailSendAndNotifyOm(new String[]{email}, null, subject, tmpl, data);
    }

    @Override
    public void notifyCompanyAcceptBySms(String phone, Map<String, String> dataMap) {
        // 短信提醒
        HashMap<String, Object> data = new HashMap<>();
        data.put("code", dataMap.get("code"));
        data.put("userName", dataMap.get("userName"));
        data.put("companyName", dataMap.get("code"));
        data.put("corp_url", userUtil.getCorpUrl(dataMap.get("org_id"), dataMap.get("code"), "", "") + "/login");
        data.put("username", StringUtils.isBlank(dataMap.get("username")) ? "superadmin" : dataMap.get("username"));
        data.put("password", StringUtils.isBlank(dataMap.get("passwd")) ? "123456" : dataMap.get("passwd"));
        data.put("hotline", CommonConstant.BEST_HOTLINE);
        data.put("expiry_date", dataMap.get("expiryDT"));
        data.put("manager_mobile", dataMap.get("manager_mobile"));
        data.put("manager_email", dataMap.get("manager_email"));
        Integer status;
        String smsContent = "";
        try {
            smsContent = StringFormatUtil.format(SmsConstant.BOOK_NOTIFY_SMS_TMPL, data);
            status = NotifyStatusEnum.IS_SEND.getType();
        } catch (Exception e) {
            log.error("send notify_company_accept_by_sms error: %s", e);
            status = NotifyStatusEnum.SEND_FAILED.getType();
        }
        smsService.sendSms(phone, smsContent);
        RecordToOmDTO recordToOmDTO = new RecordToOmDTO();
        recordToOmDTO.setContent(smsContent);
        recordToOmDTO.setName("注册成功");
        recordToOmDTO.setOrgId(dataMap.get("org_id"));
        recordToOmDTO.setReceiver(phone);
        recordToOmDTO.setType(NotifyTypeEnum.MOBILE.getType());
        recordToOmDTO.setSmsChannel(NotifySmsChannelEnum.YIMEI.getType());
        recordToOmDTO.setStatus(status);
        recordToOmDTO.setSendTime(DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
        recordToOmDTO.setTemplateId("");
        recordToOmDTO.setParams(JSON.toJSONString(dataMap));
        userUtil.recordToOm(recordToOmDTO);
    }

    @Override
    public List<OrganizationDTO> selectByInnerFlagIsNull() {
        List<OrganizationDO> organizationDOS = organizationDao.selectByInnerFlagIsNull();
        return organizationConvert.dosToDtos(organizationDOS);
    }

    @Override
    public void updateInnerFlagIsNullToFalse() {
        organizationDao.updateInnerFlagIsNullToFalse();
    }

    @Override
    public void updateInnerFlagByOrgIds(List<String> orgIds, Integer innerFlag) {
        organizationDao.updateInnerFlagByOrgIds(orgIds, innerFlag);
    }

    @Override
    public ServiceResult<Boolean> existsByCode(String code) {
        boolean exists = organizationDao.countByCode(code) > 0;
        return ServiceResult.success(exists);
    }
}
